﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DecisionTree
{
    public static class Tools
    {
        public static double Entropy(byte[] outputs, int[] idxs, byte classes)
        {
            if (idxs.Length == 0)
                return 0;

            int[] frequencies = new int[classes];
            double[] p = new double[classes];

            for (int i = 0; i < idxs.Length; i++)
                frequencies[outputs[idxs[i]]]++;

            for (int i = 0; i < classes; i++)
                p[i] = (double)frequencies[i] / idxs.Length;

            double sum = 0;
            for (int i = 0; i < p.Length; i++)
                if (p[i] != 0) sum += p[i] * Math.Log(p[i], 2);

            return -1 * sum;
        }

        public static int MostCommon(byte[] outputs, int[] idxs, int classCount)
        {
            int[] frequencies = new int[classCount];

            for (int i = 0; i < idxs.Length; i++)
                frequencies[outputs[idxs[i]]]++;

            return frequencies.MaxIndex();
        }

        /// <summary>
        ///   Computes the split information measure.
        /// </summary>
        /// 
        /// <param name="samples">The total number of samples.</param>
        /// <param name="partitions">The partitioning.</param>
        /// <returns>The split information for the given partitions.</returns>
        /// 
        public static double SplitInformation(int samples, int[][] partitions)
        {
            double info = 0;

            for (int i = 0; i < partitions.Length; i++)
            {
                double p = (double)partitions[i].Length / samples;
                if (p != 0) 
                    info -= p * Math.Log(p, 2);
            }

            return info;
        }

        public static double[] CreateHistogram(byte[] outputs, int[] idxs, int outputClasses)
        {
            double[] rVal = new double[outputClasses];

            for (int i = 0; i < idxs.Length; i++)
                rVal[outputs[idxs[i]]]++;

            double sum = rVal.Sum();

            for (int i = 0; i < outputClasses; i++)
                rVal[i] /= sum;
            
            return rVal;
        }

        public static double[] SumVectors(double[] vector1, double[] vector2)
        {
            double[] rVal = new double[vector1.Length];

            for (int i = 0; i < vector1.Length; i++)
            {
                rVal[i] = vector1[i] + vector2[i];
            }

            return rVal;
        }
    }
}
